<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>Outputting PDFs with Django &mdash; Django 1.7.8.dev20150401230226 documentation</title>
    
    <link rel="stylesheet" href="../_static/default.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../',
        VERSION:     '1.7.8.dev20150401230226',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <link rel="top" title="Django 1.7.8.dev20150401230226 documentation" href="../index.html" />
    <link rel="up" title="“How-to” guides" href="index.html" />
    <link rel="next" title="Managing static files (CSS, images)" href="static-files/index.html" />
    <link rel="prev" title="Outputting CSV with Django" href="outputting-csv.html" />



 
<script type="text/javascript" src="../templatebuiltins.js"></script>
<script type="text/javascript">
(function($) {
    if (!django_template_builtins) {
       // templatebuiltins.js missing, do nothing.
       return;
    }
    $(document).ready(function() {
        // Hyperlink Django template tags and filters
        var base = "../ref/templates/builtins.html";
        if (base == "#") {
            // Special case for builtins.html itself
            base = "";
        }
        // Tags are keywords, class '.k'
        $("div.highlight\\-html\\+django span.k").each(function(i, elem) {
             var tagname = $(elem).text();
             if ($.inArray(tagname, django_template_builtins.ttags) != -1) {
                 var fragment = tagname.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>");
             }
        });
        // Filters are functions, class '.nf'
        $("div.highlight\\-html\\+django span.nf").each(function(i, elem) {
             var filtername = $(elem).text();
             if ($.inArray(filtername, django_template_builtins.tfilters) != -1) {
                 var fragment = filtername.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + filtername + "</a>");
             }
        });
    });
})(jQuery);
</script>


  </head>
  <body>

    <div class="document">
  <div id="custom-doc" class="yui-t6">
    <div id="hd">
      <h1><a href="../index.html">Django 1.7.8.dev20150401230226 documentation</a></h1>
      <div id="global-nav">
        <a title="Home page" href="../index.html">Home</a>  |
        <a title="Table of contents" href="../contents.html">Table of contents</a>  |
        <a title="Global index" href="../genindex.html">Index</a>  |
        <a title="Module index" href="../py-modindex.html">Modules</a>
      </div>
      <div class="nav">
    &laquo; <a href="outputting-csv.html" title="Outputting CSV with Django">previous</a>
     |
    <a href="index.html" title="&amp;#8220;How-to&amp;#8221; guides" accesskey="U">up</a>
   |
    <a href="static-files/index.html" title="Managing static files (CSS, images)">next</a> &raquo;</div>
    </div>

    <div id="bd">
      <div id="yui-main">
        <div class="yui-b">
          <div class="yui-g" id="howto-outputting-pdf">
            
  <div class="section" id="s-outputting-pdfs-with-django">
<span id="outputting-pdfs-with-django"></span><h1>Outputting PDFs with Django<a class="headerlink" href="#outputting-pdfs-with-django" title="Permalink to this headline">¶</a></h1>
<p>This document explains how to output PDF files dynamically using Django views.
This is made possible by the excellent, open-source <a class="reference external" href="http://www.reportlab.com/software/opensource/rl-toolkit/">ReportLab</a> Python PDF
library.</p>
<p>The advantage of generating PDF files dynamically is that you can create
customized PDFs for different purposes &#8211; say, for different users or different
pieces of content.</p>
<p>For example, Django was used at <a class="reference external" href="http://www.kusports.com/">kusports.com</a> to generate customized,
printer-friendly NCAA tournament brackets, as PDF files, for people
participating in a March Madness contest.</p>
<div class="section" id="s-install-reportlab">
<span id="install-reportlab"></span><h2>Install ReportLab<a class="headerlink" href="#install-reportlab" title="Permalink to this headline">¶</a></h2>
<p>Download and install the ReportLab library from
<a class="reference external" href="http://www.reportlab.com/software/opensource/rl-toolkit/download/">http://www.reportlab.com/software/opensource/rl-toolkit/download/</a>.
The <a class="reference external" href="http://www.reportlab.com/docs/reportlab-userguide.pdf">user guide</a> (not coincidentally, a PDF file) explains how to install it.
Alternatively, you can also install it with <tt class="docutils literal"><span class="pre">pip</span></tt>:</p>
<div class="highlight-console"><div class="highlight"><pre><span class="gp">$</span> sudo pip install reportlab
</pre></div>
</div>
<p>Test your installation by importing it in the Python interactive interpreter:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">reportlab</span>
</pre></div>
</div>
<p>If that command doesn&#8217;t raise any errors, the installation worked.</p>
</div>
<div class="section" id="s-write-your-view">
<span id="write-your-view"></span><h2>Write your view<a class="headerlink" href="#write-your-view" title="Permalink to this headline">¶</a></h2>
<p>The key to generating PDFs dynamically with Django is that the ReportLab API
acts on file-like objects, and Django&#8217;s <a class="reference internal" href="../ref/request-response.html#django.http.HttpResponse" title="django.http.HttpResponse"><tt class="xref py py-class docutils literal"><span class="pre">HttpResponse</span></tt></a>
objects are file-like objects.</p>
<p>Here&#8217;s a &#8220;Hello World&#8221; example:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">reportlab.pdfgen</span> <span class="kn">import</span> <span class="n">canvas</span>
<span class="kn">from</span> <span class="nn">django.http</span> <span class="kn">import</span> <span class="n">HttpResponse</span>

<span class="k">def</span> <span class="nf">some_view</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="c"># Create the HttpResponse object with the appropriate PDF headers.</span>
    <span class="n">response</span> <span class="o">=</span> <span class="n">HttpResponse</span><span class="p">(</span><span class="n">content_type</span><span class="o">=</span><span class="s">&#39;application/pdf&#39;</span><span class="p">)</span>
    <span class="n">response</span><span class="p">[</span><span class="s">&#39;Content-Disposition&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;attachment; filename=&quot;somefilename.pdf&quot;&#39;</span>

    <span class="c"># Create the PDF object, using the response object as its &quot;file.&quot;</span>
    <span class="n">p</span> <span class="o">=</span> <span class="n">canvas</span><span class="o">.</span><span class="n">Canvas</span><span class="p">(</span><span class="n">response</span><span class="p">)</span>

    <span class="c"># Draw things on the PDF. Here&#39;s where the PDF generation happens.</span>
    <span class="c"># See the ReportLab documentation for the full list of functionality.</span>
    <span class="n">p</span><span class="o">.</span><span class="n">drawString</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">100</span><span class="p">,</span> <span class="s">&quot;Hello world.&quot;</span><span class="p">)</span>

    <span class="c"># Close the PDF object cleanly, and we&#39;re done.</span>
    <span class="n">p</span><span class="o">.</span><span class="n">showPage</span><span class="p">()</span>
    <span class="n">p</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
    <span class="k">return</span> <span class="n">response</span>
</pre></div>
</div>
<p>The code and comments should be self-explanatory, but a few things deserve a
mention:</p>
<ul>
<li><p class="first">The response gets a special MIME type, <em class="mimetype">application/pdf</em>. This
tells browsers that the document is a PDF file, rather than an HTML file.
If you leave this off, browsers will probably interpret the output as
HTML, which would result in ugly, scary gobbledygook in the browser
window.</p>
</li>
<li><p class="first">The response gets an additional <tt class="docutils literal"><span class="pre">Content-Disposition</span></tt> header, which
contains the name of the PDF file. This filename is arbitrary: Call it
whatever you want. It&#8217;ll be used by browsers in the &#8220;Save as...&#8221;
dialogue, etc.</p>
</li>
<li><p class="first">The <tt class="docutils literal"><span class="pre">Content-Disposition</span></tt> header starts with <tt class="docutils literal"><span class="pre">'attachment;</span> <span class="pre">'</span></tt> in this
example. This forces Web browsers to pop-up a dialog box
prompting/confirming how to handle the document even if a default is set
on the machine. If you leave off <tt class="docutils literal"><span class="pre">'attachment;'</span></tt>, browsers will handle
the PDF using whatever program/plugin they&#8217;ve been configured to use for
PDFs. Here&#8217;s what that code would look like:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">response</span><span class="p">[</span><span class="s">&#39;Content-Disposition&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;filename=&quot;somefilename.pdf&quot;&#39;</span>
</pre></div>
</div>
</li>
<li><p class="first">Hooking into the ReportLab API is easy: Just pass <tt class="docutils literal"><span class="pre">response</span></tt> as the
first argument to <tt class="docutils literal"><span class="pre">canvas.Canvas</span></tt>. The <tt class="docutils literal"><span class="pre">Canvas</span></tt> class expects a
file-like object, and <a class="reference internal" href="../ref/request-response.html#django.http.HttpResponse" title="django.http.HttpResponse"><tt class="xref py py-class docutils literal"><span class="pre">HttpResponse</span></tt></a> objects fit the
bill.</p>
</li>
<li><p class="first">Note that all subsequent PDF-generation methods are called on the PDF
object (in this case, <tt class="docutils literal"><span class="pre">p</span></tt>) &#8211; not on <tt class="docutils literal"><span class="pre">response</span></tt>.</p>
</li>
<li><p class="first">Finally, it&#8217;s important to call <tt class="docutils literal"><span class="pre">showPage()</span></tt> and <tt class="docutils literal"><span class="pre">save()</span></tt> on the PDF
file.</p>
</li>
</ul>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">ReportLab is not thread-safe. Some of our users have reported odd issues
with building PDF-generating Django views that are accessed by many people
at the same time.</p>
</div>
</div>
<div class="section" id="s-complex-pdfs">
<span id="complex-pdfs"></span><h2>Complex PDFs<a class="headerlink" href="#complex-pdfs" title="Permalink to this headline">¶</a></h2>
<p>If you&#8217;re creating a complex PDF document with ReportLab, consider using the
<a class="reference external" href="http://docs.python.org/3/library/io.html#module-io" title="(in Python v3.4)"><tt class="xref py py-mod docutils literal"><span class="pre">io</span></tt></a> library as a temporary holding place for your PDF file. This
library provides a file-like object interface that is particularly efficient.
Here&#8217;s the above &#8220;Hello World&#8221; example rewritten to use <a class="reference external" href="http://docs.python.org/3/library/io.html#module-io" title="(in Python v3.4)"><tt class="xref py py-mod docutils literal"><span class="pre">io</span></tt></a>:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">io</span> <span class="kn">import</span> <span class="n">BytesIO</span>
<span class="kn">from</span> <span class="nn">reportlab.pdfgen</span> <span class="kn">import</span> <span class="n">canvas</span>
<span class="kn">from</span> <span class="nn">django.http</span> <span class="kn">import</span> <span class="n">HttpResponse</span>

<span class="k">def</span> <span class="nf">some_view</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="c"># Create the HttpResponse object with the appropriate PDF headers.</span>
    <span class="n">response</span> <span class="o">=</span> <span class="n">HttpResponse</span><span class="p">(</span><span class="n">content_type</span><span class="o">=</span><span class="s">&#39;application/pdf&#39;</span><span class="p">)</span>
    <span class="n">response</span><span class="p">[</span><span class="s">&#39;Content-Disposition&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;attachment; filename=&quot;somefilename.pdf&quot;&#39;</span>

    <span class="nb">buffer</span> <span class="o">=</span> <span class="n">BytesIO</span><span class="p">()</span>

    <span class="c"># Create the PDF object, using the BytesIO object as its &quot;file.&quot;</span>
    <span class="n">p</span> <span class="o">=</span> <span class="n">canvas</span><span class="o">.</span><span class="n">Canvas</span><span class="p">(</span><span class="nb">buffer</span><span class="p">)</span>

    <span class="c"># Draw things on the PDF. Here&#39;s where the PDF generation happens.</span>
    <span class="c"># See the ReportLab documentation for the full list of functionality.</span>
    <span class="n">p</span><span class="o">.</span><span class="n">drawString</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">100</span><span class="p">,</span> <span class="s">&quot;Hello world.&quot;</span><span class="p">)</span>

    <span class="c"># Close the PDF object cleanly.</span>
    <span class="n">p</span><span class="o">.</span><span class="n">showPage</span><span class="p">()</span>
    <span class="n">p</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>

    <span class="c"># Get the value of the BytesIO buffer and write it to the response.</span>
    <span class="n">pdf</span> <span class="o">=</span> <span class="nb">buffer</span><span class="o">.</span><span class="n">getvalue</span><span class="p">()</span>
    <span class="nb">buffer</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
    <span class="n">response</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pdf</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">response</span>
</pre></div>
</div>
</div>
<div class="section" id="s-further-resources">
<span id="further-resources"></span><h2>Further resources<a class="headerlink" href="#further-resources" title="Permalink to this headline">¶</a></h2>
<ul class="simple">
<li><a class="reference external" href="http://www.pdflib.org/">PDFlib</a> is another PDF-generation library that has Python bindings. To
use it with Django, just use the same concepts explained in this article.</li>
<li><a class="reference external" href="http://www.xhtml2pdf.com/">Pisa XHTML2PDF</a> is yet another PDF-generation library. Pisa ships with
an example of how to integrate Pisa with Django.</li>
<li><a class="reference external" href="http://www.htmldoc.org/">HTMLdoc</a> is a command-line script that can convert HTML to PDF. It
doesn&#8217;t have a Python interface, but you can escape out to the shell
using <tt class="docutils literal"><span class="pre">system</span></tt> or <tt class="docutils literal"><span class="pre">popen</span></tt> and retrieve the output in Python.</li>
</ul>
</div>
<div class="section" id="s-other-formats">
<span id="other-formats"></span><h2>Other formats<a class="headerlink" href="#other-formats" title="Permalink to this headline">¶</a></h2>
<p>Notice that there isn&#8217;t a lot in these examples that&#8217;s PDF-specific &#8211; just the
bits using <tt class="docutils literal"><span class="pre">reportlab</span></tt>. You can use a similar technique to generate any
arbitrary format that you can find a Python library for. Also see
<a class="reference internal" href="outputting-csv.html"><em>Outputting CSV with Django</em></a> for another example and some techniques you can use
when generated text-based formats.</p>
</div>
</div>


          </div>
        </div>
      </div>
      
        
          <div class="yui-b" id="sidebar">
            
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../contents.html">Table Of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">Outputting PDFs with Django</a><ul>
<li><a class="reference internal" href="#install-reportlab">Install ReportLab</a></li>
<li><a class="reference internal" href="#write-your-view">Write your view</a></li>
<li><a class="reference internal" href="#complex-pdfs">Complex PDFs</a></li>
<li><a class="reference internal" href="#further-resources">Further resources</a></li>
<li><a class="reference internal" href="#other-formats">Other formats</a></li>
</ul>
</li>
</ul>

  <h3>Browse</h3>
  <ul>
    
      <li>Prev: <a href="outputting-csv.html">Outputting CSV with Django</a></li>
    
    
      <li>Next: <a href="static-files/index.html">Managing static files (CSS, images)</a></li>
    
  </ul>
  <h3>You are here:</h3>
  <ul>
      <li>
        <a href="../index.html">Django 1.7.8.dev20150401230226 documentation</a>
        
          <ul><li><a href="index.html">&#8220;How-to&#8221; guides</a>
        
        <ul><li>Outputting PDFs with Django</li></ul>
        </li></ul>
      </li>
  </ul>

  <h3>This Page</h3>
  <ul class="this-page-menu">
    <li><a href="../_sources/howto/outputting-pdf.txt"
           rel="nofollow">Show Source</a></li>
  </ul>
<div id="searchbox" style="display: none">
  <h3>Quick search</h3>
    <form class="search" action="../search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    <p class="searchtip" style="font-size: 90%">
    Enter search terms or a module, class or function name.
    </p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
              <h3>Last update:</h3>
              <p class="topless">Apr 02, 2015</p>
          </div>
        
      
    </div>

    <div id="ft">
      <div class="nav">
    &laquo; <a href="outputting-csv.html" title="Outputting CSV with Django">previous</a>
     |
    <a href="index.html" title="&amp;#8220;How-to&amp;#8221; guides" accesskey="U">up</a>
   |
    <a href="static-files/index.html" title="Managing static files (CSS, images)">next</a> &raquo;</div>
    </div>
  </div>

      <div class="clearer"></div>
    </div>
  </body>
</html>